<HTTP协议详解>由浅入深看HTTP
一. HTTP协议的应用简单概况
HTTP协议的主要特点可概括如下:
1.支持客户/服务器模式。
2.简单快速:客户向服务器请求服务时,只需传送请求方法和路径。请求方法常用的有GET、HEAD、POST。每种方法规定了客户与服务器联系的类型不同。由于HTTP协议简单,使得HTTP服务器的程序规模小,因而通信速度很快。
3.灵活:HTTP允许传输任意类型的数据对象。正在传输的类型由Content-Type加以标记。
4.无连接:无连接的含义是限制每次连接只处理一个请求。服务器处理完客户的请求,并收到客户的应答后,即断开连接。采用这种方式可以节省传输时间。
5.无状态:HTTP协议是无状态协议。无状态是指协议对于事务处理没有记忆能力。缺少状态意味着如果后续处理需要前面的信息,则它必须重传,这样可能导致每次连接传送的数据量增大。另一方面,在服务器不需要先前信息时它的应答就较快。
HTTP协议对其用户来讲其实是透明的,不同于如SMTP等协议的是,HTTP的报文并非是直接交付给用户去看的,最常见的场合是HTTP协议将超文本交付给浏览器或者其他超文本解析的软件来进行处理,超文本可以使用任意的标签语言如HTML,XSL,XML,XHTML。
(1)静态超文本
客户端直接通过URL请求到服务端相对应的资源,服务端直接将部署在数据库或者文件系统中的标签语言文件返还给客户端,其中可以包括其他的URL来使得客户端再次和网络中的其他主机发送HTTP请求来递归地完成超文本的解析,如HTML中的img标签。
(2)动态超文本
动态超文本需要通过软件技术来实现创建和处理动态文本,例如CGI,JavaServlet等技术,将URL中‘?’之后的动态部分做解析并生成动态文档,并且可以嵌入脚本语言交付给浏览器中的解析引擎来提高动态文档的效率,使文档中不必要的重复的部分独立解析完成,甚至可以实现活动文档,直接在文档上运行字节码形式的java程序或者javascript脚本。
二. HTTP运行事务
(1)HTTP报文分组
如下两图所示,为通用的HTTP请求和响应报文模型
请求报文 响应报文
1.请求报文
一个HTTP的完整请求报文的具体格式如下:
A.请求行--方法:
GET:请求服务器的文档
HEAD:请求关于文档的信息,但不是这个文档本身
POST:从客户向服务器发送一些信息
PUT:从服务器向客户发送文档
TRACE:把到达的请求回送
CONNECT:保留
DELETE:删除Web网页
OPTIONs:询问关于可用的选项
B.请求行--URL:
URL:统一资源定位符,是在因特网上知名任何种类的信息的标准,URL定义的是四样东西:
协议 :// 主机 : 端口 / 路径
具体详细不属于HTTP内容范畴,暂且不赘述。
C.请求行--版本:
目前HTTP的最新版本是1.1,旧版本还有1.0等,具体相关定义在对应RFC中可以查找。
D.请求报文的首部行:(个别书上也把这个叫做头域)
首部行是客户向服务器发送信息时的附加信息,数量为零到多个,如上图所示的格式,每个首部行占有一个首部名,一个冒号,一个空格和一个首部值。在RFC中完整的首部值列表及分类如下所示:(其中上颜色的为较常用首部名称)
a.通用首部:既可以出现在请求报文中,也可以出现在响应报文中。这些是客户端和服务器都可以使用的通用首部。可以在客户端、服务器和其他应用程序之间提供一些非常有用的通用功能。不论报文是何种类型,都为其提供一些有用的信息。例如不管是构建请求报文还是响应报文,创建报文的日期时间都是同一个意思,因此提供这类信息的首部对这两种类型的报文来说都是通用的。下面用表格的形式给出通用的信息性首部。
通用的信息性首部:
首部 描述
Connection 允许客户端和服务器指定与请求/响应连接有关的选项
Date 提供日期和时间标志,说明报文是什么时间创建的
MIME-Version 给出了发送端使用的MIME版本
Trailer 如果报文采用了分块传输编码(chunked transfer encoding)方式,就可以用这个首部列出位于报文拖鞋 (trailer)部分的首部集合。
Transfer-Encoding 告知接收端为了保证报文的可靠传输,对报文采用了什么编码方式。
Update 给出了发送端可能想要"升级"使用的新版本或协议
Via 显示了报文经过的中间节点(代理、网关)
通用缓存首部:
首部 描述
Cache-Control 用于随报文传送缓存指示
Pragma 另一种随报文传送指示的方式,但并不专用于缓存
b.请求首部:提供更多有关请求的信息。请求首部是在请求报文中有意义的首部。用于说明是谁或什么在发送请求,请求源自何处,或者客户端的喜好及能力。服务器可以根据请求首部给出的客户端的信息,试着为客户端提供更好的响应。
首部 描述
Client-IP 提供了运行客户端的机器的IP地址
From 提供了客户端用户的E-mail地址
Host 给出了接收请求的服务器的主机名和端口号
Referer 提供了包含当前请求URI的文档的URL
UA-Color 提供了与客户端显示器的显示颜色有关的信息
UA-CPU 给出了客户端CPU的类型或制造商
US-Disp 提供了与客户端显示器(屏幕)能力有关的信息
US-OS 给出了客户端显示器的像素信息
UA-Pixels 提供了客户端显示器的像素信息
User-Agent 将发起请求的应用程序名称告知服务器(User-Agent)用户代理
Accept首部为客户端提供了一种将其喜好和能力告知服务器的方式,包括他们想要什么,可以使用什么,以及最重要的,他们不想要什么。这样服务器就可以根据这些额外信息,对要发送的内容做出更明智的决定。Accept首部会使连接的两端都受益。客户端会得到他们想要的内容,服务器则不会浪费其时间和带宽来发送客户端无法使用的东西。
首部 描述
Accept 告诉服务器能够发送哪些媒体类型
Accept-Charset 告诉服务器能够发送哪些字符集
Accept-Encoding 告诉服务器能够发送哪些编码方式
Accept-Language 告诉服务器能够发送哪些语言
TE 告诉服务器可以使用哪些扩展传输编码
条件请求首部:有时客户端希望为请求加上某些限制。比如客户端已经有了一份副本,就希望只在服务器上的文档与客户端拥有的副本有所区别时,才请求服务器传输文档。通过条件请求首部,客户端就可以加上这种限制,要求服务器在对请求进行相应之前,确保某个请求为真。
首部 描述
Expect 允许客户端列出某请求所要求的服务器行为
If-Match 如果实体标记与文档当前的实体标记相匹配,就或者这份文档
If-Modified-Since 除非在某个指定的日期之后资源被修改过,否则就限制这个请求
If-Range 允许对文档的某个范围进行条件请求
If-Unmodified-Since 除非在某个指定的日期之后资源没有被修改过,否则就限制这个请求
Range 如果服务器支持范围请求,就请求资源的指定范围
安全请求首部:HTTP本身就支持一种简单的机制,可以对请求进行质询/响应认证。这种机制要求客户端在获取特定的资源之前,先对自身进行认证,这样就可以使事务稍微安全一些。
首部 描述
Authorization 包含了客户端提供给服务器,以便对其自身进行认证的数据
Cookie 客户端用它想服务器传送一个令牌-他并不是真正的安全首部,但却是隐含了安全功能
Cookie2 用来说明请求端支持的cookie版本
代理请求首部:随着因特网上代理的普遍应用,人们定义了几个首部来协助其更好地工作。
首部 描述
Max-Forword 在通往源端服务器的路径上,将请求转发给其他代理或网关的最大次数-与TRACE方法一同使用
Proxy-Authorization 与Authorization首部相同,但这个首部是在与代理进行认证时使用的
Proxy-Connection 与Connection首部相同,但这个首部是在于代理建立连接时使用的
c.响应首部:提供更多有关响应的信息。响应报文由自己的响应首部集。响应首部为客户端提供了一些额外的信息,比如谁在发送响应、响应者的功能,甚至与响应相关的一些特殊指令。这些首部有助于客 户端处理响应,并在将来发起更好的请求。
首部 描述
Age (从最初创建开始)响应持续时间
Public 服务器为其资源支持的请求方法列表
Retry-After 如果资源不可用的话,再次日期或时间重试
Server 服务器应用程序软件的名称和版本
Title 对HTML文档来说,就是HTML文档的源端给出的标题
Warning 比原因短语中更详细的一些警告报文
协商首部:如果资源有多种表示方法-比如,如果服务器上有某文档的法语和德语译稿,HTTP/1.1可以为服务器和客户端提供对资源进行协商的能力。
首部 描述
Accept-Ranges 对此资源来说,服务器可接受的范围类型
Vary 服务器查看的其他首部的列表,可能会使响应发生变化;也就是说,这是一个首部列表,服务器会根据这些首部的内容挑选出最合适的资源版本发送给客户端。
安全响应首部:
我们已经看到过安全请求首部了,本质上这里说的就是HTTP的质询/响应认证机制的响应侧。
首部 描述
Proxy-Authenticate 来自代理的对客户端的质询列表
Set-Cookie 不是真正的安全首部,但隐含有安全功能;可以在客户端设置一个令牌,以便服务器对客户端进行标识。
Set-Cookie2 与Set-Cookie类似。
WWW-Authenticate 来自服务器的对客户端的质询列表
d、实体首部:描述主体的长度和内容,或者资源自身。有很多首部可以用来描述HTTP报文的负荷。由于请求和响应文本中都可能包含实体部分,所以在这两种类型的报文中都可能出现这些首部。实体首部提供了有关实体及其内容的大量信息,从有关对象类型的信息,到能够对资源使用的各种有效的请求方法。总之,实体首部可以告知报文的接收者它在对什么进行处理。
首部 描述
Allow 列出了可以对此实体执行的请求方法
Location 告知客户端实体实际上位于何处;用于将接收端定向到资源的位置上去
内容首部:内容首部提供了与实体内容有关的特定信息,说明了其类型、尺寸以及处理它所需的其他有用信息。比如,Web浏览器可以通过查看返回的内容类型,得知如何显示对象。
首部 描述
Content-Base 解析主体中的相对URL时使用的基础URL
Content-Encoding 对主体执行的任意编码方式
Content-Language 理解主体时最适宜使用的自然语言
Content-Length 主体的长度或尺寸
Content-Location 资源实际所处的位置
Content-MD5 主体的MD5校验
Content-Range 在整个资源中此实体表示的字节范围
Content-Type 这个主体的对象模型
实体缓存首部:通用的缓存首部说明了如何或什么时候进行缓存。实体的缓存首部提供了与被缓存实体有关的信息,比如验证已缓存的资源副本是否仍然有效所需的信息,以及更好地估计已缓存资源合适失效所需的线索。
首部 描述
ETag 与此实体有关的实体标记
Expires 实体不在有效,要从原始的源端再次获取此实体的日期和时间
Last-Modified 这个实体最后一次被修改的日期和时间
首部行有的时候为了提高可读性会被分为多行来提高可读性,将其值划分为多个延续行,每个延续行的前面至少要有一个空格或者一个制表符。请求报文的实体是一些需要发送的备注性信息。
2.响应报文
一个HTTP的完整响应报文的具体格式如下:
A.状态行--版本:同请求行--版本
B.状态行--状态码:
大致分类如下所示:
100-199 用于指定客户端应相应的某些动作。
200-299 用于表示请求成功。
300-399 用于已经移动的文件并且常被包含在定位头信息中指定新的地址信息。
400-499 用于指出客户端的错误。
500-599 用于支持服务器错误。
具体的状态码参见:http://www.cnblogs.com/lxinxuan/archive/2009/10/22/1588053.html
C.状态行--短语:所谓的短语是和状态码相对应的,如常见的404状态码对应Not found,403对应Forbidden
D.响应报文的首部行:参见请求报文的首部行
响应报文的实体与请求报文不同,主要存放的是服务端向客户端发送的文档,如果响应不是错误报文,则实体出现在响应报文中。
(2)连接模型
如上图所示,尽管服务端使用了80号端口作为TCP连接的接收端,但HTTP本身是个无状态的协议,服务端不会保留关于客户端的信息,每次HTTP永远是客户端先发起请求,然后服务端回送响应。
关于长连接和短连接:
从HTTP1.1之后默认使用了长连接,在HTTP1.0中使用的是HTTP首部Connection:Keep-alive来进行长连接的实验性拓展。长连接使数据传输完成之后保持TCP连接不断开,等待在同域名下继续使用这个通道传输数据,与之相对应的就是短连接,从HTTP1.1开始要在HTTP请求报文中使用Connection:close来通知不希望使用长连接。在短连接中,对每一个请求/响应都要建立一次TCP连接,举个例子如某一个超文本文档上有N个位于同一个服务器的图片时,那么就要先后对该图片所在的服务器打开和关闭N+1次TCP连接,短链接会给服务器带来巨大的不必要的开销,也减慢了连接建立和关闭的过程。在使用了长连接之后,服务器允许TCP连接的保持已减少握手过程,服务器也可以在客户端请求时或者请求超时时关闭这个连接,在某些情况下,服务器并不知道要发送的文档的长度,那么服务器就要把长度未知这个首部通知客户,并在发送数据后关闭这个连接,因此客户就可以知道数据结束的地方就要到了。另外在首部中可以通过定义Keep-Alive首部来定义TCP连接的最长使用限时。实际上头部有了Connection: Keep-alive这个首部并不代表服务器一定就会使用长连接,客户端和服务端都可以忽略这个首部的定义。如下所示为长连接的连接模式图:
长连接模式下。当客户端向服务器发生请求之后,客户端如何判断服务器的数据已经发生完成?除了通过服务器关闭连接来被动的关闭HTTP的TCP连接之外,可以通过消息首部字段Content-Length来判断数据传输是否完毕,单位为字节,另外也可以通过使用消息首部字段Transfer-Encoding来协助完成判断,Transfer-Encoding:clunk或者Transfer-Encoding:clunked模式可以将数据分为一块一块的传输,clunk编码的具体格式这里暂不赘述。
关于HTTP中的Cookie:
Cookie的实质就是一个键值对,当一个客户端向服务端发送请求的时候,浏览器就查找在Cookie目录中是否有那个服务器发送的Cookie,如果有的话就会把相应的Cookie包含对请求之中,当这个Cookie包含在请求之中的时候服务端就可以知道这个客户是一个老客户,cookie的使用者和消费者都是服务端,这对于浏览器和消费者都是透明的。在HTTP报文分组中,与其功能相关的首部是Cookie首部和Set-Cookie首部。具体格式如下所示:
Set-Cookie:value [ ;expires=date][ ;domain=domain][ ;path=path][ ;secure]
Cookie : value
Cookie:value1 ; value2 ; name1=value1
在Set-Cookie中,可以通过定义选项的值来进一步确定Cookie的功能。
1.有效期选项(The expires option)
紧跟cookie值后面的每个选项都以分号和空格分割,并且每个选项都指定cookie何时应该被发送到服务器。第一个选项是expires,其指定了cookie何时不会再被发送到服务器端的,因此该cookie可能会被浏览器删掉。例如:
1 |
Set-Cookie:name=Nicholas;expires=Sat, 02 May 2009 23:38:25 GMT |
在没有expires选项时,cookie的寿命仅限于单一的会话中。浏览器的关闭意味这一次会话的结束,所以会话cookie只存在于浏览器保持打开的状态之下。这就是为什么当你登录到一个web应用时经常看到一个checkbox,询问你是否选择存储你的登录信息:如果你选择是的话,那么一个expires选项会被附加到登录的cookie中。如果expires选项设置了一个过去的时间点,那么这个cookie会被立即删除。
2.域选项(The domain option)
下一个选项是domain,指示cookie将要发送到哪个域或那些域中。默认情况下,domain会被设置为创建该cookie的页面所在的域名。例如本站中的cookie的domain属性的默认值为www.nczonline.com。domain选项被用来扩展cookie值所要发送域的数量。例如:
1 |
Set-Cookie:name=Nicholas;domain=nczonline.net |
domain设置的值必须是发送Set-Cookie消息头的域名。例如,我无法向google.com发送一个cookie,因为这个产生安全问题。不合法的domain选项只要简单的忽略即可。
3.Path选项(The path option)
另一个控制何时发送Cookie消息头的方式是指定path选项。与domain选项相同的是,path指明了在发Cookie消息头之前必须在请求资源中存在一个URL路径。这个比较是通过将path属性值与请求的URL从头开始逐字符串比较完成的。如果字符匹配,则发送Cookie消息头,例如:
1 |
Set-Cookie:name=Nicholas;path=/blog |
在这个例子中,path选项值会与/blog,/blogrool等等相匹配;任何以/blog开头的选项都是合法的。要注意的是只有在domain选项核实完毕之后才会对path属性进行比较。path属性的默认值是发送Set-Cookie消息头所对应的URL中的path部分。
4.secure选项(The secure option)
最后一个选项是secure。不像其它选项,该选项只是一个标记并且没有其它的值。一个secure cookie只有当请求是通过SSL和HTTPS创建时,才会发送到服务器端。这种cookie的内容意指具有很高的价值并且可能潜在的被破解以纯文本形式传输。例如
1 |
Set-Cookie:name=Nicholas;secure |
现实中,机密且敏感的信息绝不应该在cookies中存储或传输,因为cookies的整个机制都是原本不安全的。默认情况下,在HTTPS链接上传输的cookies都会被自动添加上secure选项。
关于HTTP的安全:
HTTP本身并不提供安全,然而通过在传输层和应用层中使用安全套接层(SSL)可以使HTTP运行在安全的环境下,即HTTPS,HTTPS可以提供保密性,客户和服务器鉴别以及数据的完整性。
SSL的设计时为了给应用层生成的数据提供安全以及压缩服务,一般来说SSL能接收来自任何应用层协议的数据,但最多情况下这个应用层的协议就是HTTP,SSL对应用层传来的数据提供多种服务:
分片:SSL把数据划分为长度小于或者等于2的14次字节的数据分片
压缩:数据分片通过使用一种由客户端和服务器协商好的无损压缩方式进行压缩,这个服务是可选的。
报文完整性:为了保护数据的完整性,SSL使用密钥散列函数来创建MAC。
保密:为了提供保密性,原始的数据和MAC一起用对称密钥加密技术来加密。
组帧:先在被加密的有效载荷上添加一个首部,然后再把这个恶有效载荷传递给可靠的运输层协议。